
#include <BPainter>
#include "member_BGridLayout.h"

using namespace BWE;

member_BGridLayout::member_BGridLayout(BGridLayout* layout)
{
	boss = layout;
}
member_BGridLayout::~member_BGridLayout()
{

}

void member_BGridLayout::expandTable(int row, int column)
{
	if (rows.size() < row + 1)
	{
		rows.resize(row + 1);
		items.setRow(row + 1);
	}
	if (cols.size() < column + 1)
	{
		cols.resize(column + 1);
		items.setColumn(column + 1);
	}
}

void member_BGridLayout::prepare()
{
	for(int i = 0; i < rows.size(); i++)
		rows[i].init();

	for(int i = 0; i < cols.size(); i++)
		cols[i].init();

	for (int r = 0; r < items.row(); r++)
	{
		for (int c = 0; c < items.column(); c++)
		{
			LayoutItem& item = items[r][c];
			//igored hint
			if (item.ignored())
				continue;

			rows[r].ignored = false;
			cols[c].ignored = false;

			//size policy
			if (item.sizePolicy().widthPolicy() & Policy_Expanding)
				cols[c].finished = false;
			if (item.sizePolicy().heightPolicy() & Policy_Expanding)
				rows[r].finished = false;

			//hintSize
			BSize minSize = item.minSize();
			BSize maxSize = item.maxSize();
			BSize realSize = item.sizeHint();

			item.realSize = realSize;

			if (rows[r].hintHeight < realSize.height())
				rows[r].hintHeight = realSize.height();
			if (cols[c].hintWidth < realSize.width())
				cols[c].hintWidth = realSize.width();

			if (rows[r].height < realSize.height())
				rows[r].height = realSize.height();
			if (cols[c].width < realSize.width())
				cols[c].width = realSize.width();

			//minSize
			if (rows[r].minSize.height() < minSize.height())
				rows[r].minSize.setHeight(minSize.height());
			if (cols[c].minSize.width() < minSize.width())
				cols[c].minSize.setWidth(minSize.width());

			//maxSize
			if (rows[r].maxSize.height() < maxSize.height())
				rows[r].maxSize.setHeight(maxSize.height());
			if (cols[c].maxSize.width() < maxSize.width())
				cols[c].maxSize.setWidth(maxSize.width());

			//stretch
			if (rows[r].stretch < item.sizeStretch().heightStretch())
				rows[r].stretch = item.sizeStretch().heightStretch();

			if (cols[c].stretch < item.sizeStretch().widthStretch())
				cols[c].stretch = item.sizeStretch().widthStretch();

		}
	}

	int border = boss->border();
	int space = boss->space();
	const BSize& minSize = boss->minSize();
	const BSize& maxSize = boss->maxSize();

	int totalWidth = border + border;
	int totalHeight = border + border;
	for (int i = 0; i < cols.size(); i++)
	{
		if (cols[i].fixedStretch > 0.000001f)
			cols[i].stretch = cols[i].fixedStretch;
		totalWidth += cols[i].hintWidth + space;
	}
	for (int i = 0; i < rows.size(); i++)
	{
		if (rows[i].fixedStretch > 0.000001f)
			rows[i].stretch = rows[i].fixedStretch;
		totalHeight += rows[i].hintHeight + space;
	}
	totalWidth -= space;
	totalHeight -= space;
	int hintWidth = bLimit(totalWidth, minSize.width(), maxSize.width());
	int hintHeight = bLimit(totalHeight, minSize.height(), maxSize.height());
	if (totalWidth != hintWidth)
	{
		int remainHeight = hintHeight - totalHeight;
		float totalStretch = 0;
		for (int r = 0; r < items.row(); r++)
			totalStretch += rows[r].stretch;
		for (int r = 0; r < items.row(); r++)
		{
			rows[r].hintHeight += remainHeight * rows[r].stretch / totalStretch;
			rows[r].height = rows[r].hintHeight;
		}
	}
	if (totalHeight != hintHeight)
	{
		int remainWidth = hintWidth - totalWidth;
		float totalStretch = 0;
		for (int c = 0; c < items.column(); c++)
			totalStretch += cols[c].stretch;
		for (int c = 0; c < items.column(); c++)
		{
			cols[c].hintWidth += remainWidth * cols[c].stretch / totalStretch;
			cols[c].width = cols[c].hintWidth;
		}
	}
}
void member_BGridLayout::distributeWidth(int remainWidth)
{
	while (remainWidth != 0)
	{
		float totalStretch = 0;
		for (int c = 0; c < items.column(); c++)
			totalStretch += cols[c].stretch;
		if (totalStretch < 0.00001)
			break;

		int used = 0;
		for (int c = 0; c < items.column(); c++)
		{
			if (cols[c].finished)
				continue;
			int width = cols[c].stretch / totalStretch * remainWidth;
			int maxWidth = cols[c].maxSize.width();
			int minWidth = cols[c].minSize.width();
			if (width + cols[c].width > maxWidth)
			{
				used += maxWidth - cols[c].width;
				cols[c].width = maxWidth;
				cols[c].finished = true;
				continue;
			}
			if (width + cols[c].width < minWidth)
			{
				used += minWidth - cols[c].width;
				cols[c].width = minWidth;
				cols[c].finished = true;
				continue;
			}
			used += width;
			cols[c].width += width, 0;
		}
		if (used == 0)
			break;
		remainWidth -= used;
	}
}
void member_BGridLayout::distributeHeight(int remainHeight)
{
	while(remainHeight != 0)
	{
		float totalStretch = 0;
		for(int r = 0; r < items.row(); r++)
			totalStretch += rows[r].stretch;

		int used = 0;
		for (int r = 0; r < items.row(); r++)
		{
			if (rows[r].finished)
				continue;
			int height = rows[r].stretch / totalStretch * remainHeight;
			int maxHeight = rows[r].maxSize.height();
			int minHeight = rows[r].minSize.height();
			if (rows[r].height + height > maxHeight)
			{
				used += maxHeight - rows[r].height;
				rows[r].height = maxHeight;
				rows[r].finished = true;
				continue;
			}
			if (rows[r].height + height < minHeight)
			{
				used += minHeight - rows[r].height;
				rows[r].height = minHeight;
				rows[r].finished = true;
				continue;
			}
			used += height;
			rows[r].height += height;
		}
		if(used == 0)
			break;
		remainHeight -= used;
	}
}
